using System;
using System.Collections.Specialized;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Utilities;


namespace OrbitOne.SharePoint.Provision.WebParts
{
    public class SharePointProvisioning
    {

        public SharePointProvisioning()
        {
        }

        public static void hstCreateSite(string webAppURL, string strURL, string strTitle, string strDesc, uint nLCID, string strTemplate,
                                    string strOwnerLogin1, string strOwnerName1, string strOwnerEmail1,
                                    string strOwnerLogin2, string strOwnerName2, string strOwnerEmail2,
                                    bool hhMode)
        {
            System.Uri srvrUri = new System.Uri(webAppURL);
            SPWebApplication webApp = SPWebApplication.Lookup(srvrUri);

            SPSiteCollection siteColl = webApp.Sites;
            SPSite oSite = null;
            try
            {
                // If the secondary owner fields are empty, convert them to null
                if (String.IsNullOrEmpty(strOwnerLogin2)) strOwnerLogin2 = null;
                if (String.IsNullOrEmpty(strOwnerName2)) strOwnerName2 = null;
                if (String.IsNullOrEmpty(strOwnerEmail2)) strOwnerEmail2 = null;

                // elevate permissions to allow user to create a new site.
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    // add site to the site collection
                    oSite = siteColl.Add(strURL, strTitle, strDesc, nLCID, strTemplate,
                                strOwnerLogin1, strOwnerName1, strOwnerEmail1,
                                strOwnerLogin2, strOwnerName2, strOwnerEmail2, true);

                });
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                // dispose object
                if (oSite != null)
                    oSite.Dispose();
              
               
            }

        }
 
        public static void hstDeleteSite(string webAppURL, string strSiteURL, bool bDeleteUsers)
        {

            System.Uri srvrUri = new System.Uri(webAppURL);
            SPWebApplication webApp = SPWebApplication.Lookup(srvrUri);

            try
            {
                SPSiteCollection siteColl = webApp.Sites;
                string[] siteURLS = siteColl.Names;
                // iterate through the site collection to make sure we're deleting a site that exists.
                foreach (string url in siteURLS)
                {
                    if (url.ToLower() == strSiteURL.ToLower())
                    {
                        // elevate permissions to allow user to delete a site.
                        SPSecurity.RunWithElevatedPrivileges(delegate()
                        {
                            // delete site from the site collection
                            siteColl.Delete(url, bDeleteUsers);
                        });
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public static string hstCreateWebApp(string siteName, string ContentDBSvr, string ContentDBName,
                                    string ContentDBLogin, string ContentDBPwd,
                                    string AppPoolID, string AppPoolUserName, string AppPoolPwd,
                                    string strSvrComment, int Port)
        {

            try
            {
                SPFarm farm = SPFarm.Local;
                // specify Web Application properties
                SPWebApplicationBuilder webAppBldr = new SPWebApplicationBuilder(farm);
                webAppBldr.ServerComment = strSvrComment;
                webAppBldr.Port = Port; 
                webAppBldr.DefaultZoneUri = new Uri(siteName);
                webAppBldr.UseNTLMExclusively = true;

                // Specify AppPool to use
                webAppBldr.ApplicationPoolId = AppPoolID;
                webAppBldr.ApplicationPoolUsername = AppPoolUserName;
                System.Security.SecureString secString = new System.Security.SecureString();
                foreach (char c in AppPoolPwd.ToCharArray())
                {
                    secString.AppendChar(c);
                }
                webAppBldr.ApplicationPoolPassword = secString;

                // specify Database name
                if (ContentDBName.Length > 0)
                {
                    webAppBldr.CreateNewDatabase = true;
                    webAppBldr.DatabaseServer = ContentDBSvr;
                    webAppBldr.DatabaseName = ContentDBName;
                    // todo: determine which identity can be used 
                    //webAppBldr.DatabasePassword = ContentDBPwd;
                    //webAppBldr.DatabaseUsername = ContentDBLogin;
                }

                // elevate permissions to allow user to create a Web App.
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    // create WSS Web App
                    SPWebApplication webApp = webAppBldr.Create();

                    // create IIS site
                    webApp.Provision();
                });
                return "WebApp is created and provisioned";

            }
            catch (Exception ex)
            {
                return (ex.Message + " -- " + ex.StackTrace);
            }
        }


        public static void hstSetSiteProperty(string strSiteURL, string strPropertyName, string strPropertyValue)
        {


            SPSite oSite = new SPSite(strSiteURL);
            SPWeb oWeb = oSite.OpenWeb();

            try
            {
                //// elevate permissions to allow user to create a new site property.
                //oWeb = oSite.OpenWeb();
                oWeb.AllowUnsafeUpdates = true;
                // add new property name and value
                oWeb.Properties.Add(strPropertyName, strPropertyValue);
                oWeb.Properties.Update();
                oWeb.AllowUnsafeUpdates = false;

                //});
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {

                // dispose objects
                if (oWeb != null)
                    oWeb.Dispose();

                if (oSite != null)
                    oSite.Dispose();
            }
        }

        public static string hstGetSiteProperty(string strSiteURL, string strPropertyName)
        {
            SPSite oSite = new SPSite(strSiteURL);
            SPWeb oWeb = oSite.OpenWeb();
            // check for property existence
            foreach (System.Collections.DictionaryEntry props in oWeb.Properties)
            {
                // if property exist, get the value
                if (props.Key.ToString() == strPropertyName.ToLower())
                {
                    string strValue = props.Value.ToString();
                    return (strValue);
                }
            }
            // dispose objects
            if (oWeb != null)
                oWeb.Dispose();

            if (oSite != null)
                oSite.Dispose();
            throw new Exception("Site Property: " + strPropertyName + " does not exists");

        }

        public static void hstAddUsertoSite(string strSiteURL, string strUserLogin, string strUserName, string strUserEmail)
        {
            SPSite oSite = new SPSite(strSiteURL);
            SPWeb oWeb = oSite.OpenWeb();
            
            // get site's user collection
            SPUserCollection userColl = oWeb.AllUsers;

            // if user exists, throw exception 
            foreach (SPUser user in userColl)
            {
                if (user.LoginName.ToLower() == strUserLogin.ToLower())
                {
                    throw new Exception("User " + strUserLogin + " already exists.");
                }
            }
            try
            {


                using (ElevationManager evelate = new ElevationManager())
                {
                    oWeb.AllUsers.Add(strUserLogin, strUserEmail, strUserName, null);

                    // get the user object to assign a role
                    SPUser spUser = oWeb.AllUsers[strUserLogin];
                    
                    string strGroup = ConfigurationManager.AppSettings["defaultGroupNameForNewUser"];

                    if (!string.IsNullOrEmpty(strGroup) && oWeb.SiteGroups[strGroup]!=null)
                    {
                        //Open group
                        SPGroup spGroup = oWeb.SiteGroups[strGroup];

                        //Add and update group with new user
                        spGroup.AddUser(spUser.LoginName, spUser.Email, spUser.Name,string.Empty);
                        spGroup.Update();
                    }

                    else
                    {
                        // get the reader role
                        SPRoleDefinitionCollection roleDefsColl = oWeb.RoleDefinitions;

                        SPRoleDefinition readRoleDef = null;
                        foreach (SPRoleDefinition roleDef in roleDefsColl)
                        {
                            if (roleDef.Type == SPRoleType.Reader)
                            {
                                readRoleDef = roleDef;
                                break;
                            }
                        }

                        // create a new role assignment for the user
                        SPRoleAssignment ra = new SPRoleAssignment(spUser);

                        // elevate permissions to allow new user to be added to the role.

                        // add the user to the role
                        ra.RoleDefinitionBindings.Add(readRoleDef);

                        // add the role assignment to the site
                        oWeb.RoleAssignments.Add(ra);

                        // apply the update.
                       
                    }
                    oWeb.Update();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                //dispose objects
                if (oWeb != null)
                    oWeb.Dispose();

                if (oSite != null)
                    oSite.Dispose();
            }
        }


        public static void hstSendEmail(string fullName, string senderFullName, string strSiteURL, string strUserLogin, string strUserEmail, string strUserPwd, int emailTemplate)
        {
            string NewUserInvite =
                @"<html><head></head><body>
Dear $$RecieverName$$,<br>
($$UserLogin$$) has granted you access to
<a target= href=$$SiteURL$$>$$SiteURL$$</a>.<br>
Click the link to view the site.
<p>Your user name and password for accessing this Web site are: </p>
<blockquote>
	<b>User name:</b><br>
	$$InvitedUserLogin$$
	<p>&nbsp;</p>
</blockquote>
<blockquote>
	<b>Password:</b><br>
	<span>$$InvitedUserPwd$$</span>
	<p>&nbsp;</p>
</blockquote>
</body></html>";
            string ExistingUserInvite =
                @"<html><head></head><body>
Dear $$RecieverName$$,<br>
($$UserLogin$$) has granted you access to
<a target= href=$$SiteURL$$>$$SiteURL$$</a>.<br>
Click the link to view the site.
<p>Please user your existing user name and password to access this Web site. </p>
<blockquote>
	<b>User name:</b><br>
	$$InvitedUserLogin$$
	<p>&nbsp;</p>
</blockquote>
</body></html>";

            string mailTemplate = ReadMailTemplate();
            if (!string.IsNullOrEmpty(mailTemplate))
            {
                NewUserInvite = mailTemplate;
                ExistingUserInvite = mailTemplate;
            }

            //WindowsIdentity id = WindowsIdentity.GetCurrent();


            bool bAppendHtmlTag = false;
            bool bHTMLEnc = false;

            string siteLink = @"" + strSiteURL + @"";
            string strHTMLBody = "";

            // determine invitation and replace any placeholders
            if (emailTemplate == 1)
            {
                strHTMLBody = NewUserInvite;
                strHTMLBody = strHTMLBody.Replace("$$RecieverName$$", fullName);
                strHTMLBody = strHTMLBody.Replace("$$SiteURL$$", siteLink);
                strHTMLBody = strHTMLBody.Replace("$$UserLogin$$", senderFullName); //id.Name);
                strHTMLBody = strHTMLBody.Replace("$$InvitedUserLogin$$", strUserLogin);
                strHTMLBody = strHTMLBody.Replace("$$InvitedUserPwd$$", strUserPwd);
                //strHTMLBody = strHTMLBody.Replace("$$ChangePwdPage$$", pwdLink);
            }
            else
            {
                strHTMLBody = ExistingUserInvite;
                strHTMLBody = strHTMLBody.Replace("$$RecieverName$$", fullName);
                strHTMLBody = strHTMLBody.Replace("$$SiteURL$$", siteLink);
                strHTMLBody = strHTMLBody.Replace("$$UserLogin$$", senderFullName); //id.Name);
                strHTMLBody = strHTMLBody.Replace("$$InvitedUserLogin$$", strUserLogin);
            }


            string strSubject = ConfigurationManager.AppSettings["emailSubject"];
            if (string.IsNullOrEmpty(strSubject)) strSubject = "SharePoint Site Invitation";


            StringDictionary messageHeader = new StringDictionary();
            messageHeader.Add("to", strUserEmail);
            if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["emailCc"]))
            {
                messageHeader.Add("cc", ConfigurationManager.AppSettings["emailCc"]);
            }
            if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["emailBCc"]))
            {
                messageHeader.Add("bcc", ConfigurationManager.AppSettings["emailBcc"]);
            }
            if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["emailFromAddress"]))
            {
                 messageHeader.Add("from", ConfigurationManager.AppSettings["emailFromAddress"]);
            }
            messageHeader.Add("subject", strSubject);
            messageHeader.Add("content-type", "text/html");


            SPSite oSite = new SPSite(strSiteURL);
            SPWeb oWeb = oSite.OpenWeb();
            try
            {
                // send mail
                bool result = SPUtility.SendEmail(oWeb, messageHeader,strHTMLBody);
                
                if (!result)
                {
                    Exception ex = new Exception("Send email to user failed.");
                    ex.Data.Add("MailSendingFailedMessage", "Failed without exception");
                    throw ex;
                }
            }
            catch (Exception ex)
            {
                if (!ex.Data.Contains("MailSendingFailedMessage"))
                {
                    ex.Data.Add("MailSendingFailedMessage", "Failed with exception");
                }
                throw ex;
            }
            finally
            {
                //dispose objects
                if (oWeb != null)
                    oWeb.Dispose();

                if (oSite != null)
                    oSite.Dispose();
            }
        }


        private static string ReadMailTemplate()
        {
            string result = string.Empty;
            string templateFilePath = 
                System.Web.HttpContext.Current.Server.MapPath(ConfigurationManager.AppSettings["emailTemplateFile"]);
            
            if (File.Exists(templateFilePath))
            {
                StreamReader reader = new StreamReader(templateFilePath);
                result = reader.ReadToEnd();
                reader.Close();
            }
            
            return result;
        }


        public static void hstSetPeoplePickerProperty(string webAppUrl)
        {
            try
            {
                // elevate permissions to allow setting of property.
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    System.Uri srvrUri = new System.Uri(webAppUrl);
                    SPWebApplication webApp = SPWebApplication.Lookup(srvrUri);

                    // if property is false, set it to true
                    if (!webApp.PeoplePickerSettings.OnlySearchWithinSiteCollection)
                    {
                        webApp.PeoplePickerSettings.OnlySearchWithinSiteCollection = true;
                        webApp.Update();
                    }
                });

            }
            catch (Exception ex)
            {
                throw ex;
            }

        }

        /// <summary>
        /// Get the current user display name
        /// </summary>
        /// <returns>Display name</returns>
        internal static string GetCurrentDisplayName()
        {
            SPWeb oWeb;
            SPUser oUser;
            string displayName = String.Empty;

            oWeb = SPContext.Current.Web;
            oUser = oWeb.CurrentUser;

            try
            {
                displayName = oUser.Name;
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return displayName;
        }

    } 

}
